# Imports
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.offline as pyoff
import plotly.graph_objs as go
from datetime import datetime, timedelta
%matplotlib inline
pyoff.init_notebook_mode()
from platform import python_version
print("A versão de Python usada é: ", python_version())
A versão de Python usada é: 3.9.7
import watermark
%reload_ext watermark
%watermark -a "Alan Figueroa" --iversions
Author: Alan Figueroa pandas : 1.3.4 plotly : 5.6.0 seaborn : 0.11.2 watermark : 2.3.0 matplotlib: 3.4.3 numpy : 1.20.3
# Carregar os dados
dados = pd.read_csv('dados/dataset.csv', header=0, encoding='unicode_escape')
# Visualizando
dados.head()
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | |
|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 12/1/2010 8:26 | 4.25 | 17850.0 | Brasil |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 12/1/2010 8:26 | 2.55 | 17850.0 | Brasil |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 12/1/2010 8:26 | 3.39 | 17850.0 | Brasil |
| 3 | 536365 | 84406B | CREAM CUPID HEARTS COAT HANGER | 8 | 12/1/2010 8:26 | 2.75 | 17850.0 | Brasil |
| 4 | 536365 | 84029G | KNITTED UNION FLAG HOT WATER BOTTLE | 6 | 12/1/2010 8:26 | 3.39 | 17850.0 | Brasil |
dados.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 541800 entries, 0 to 541799 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 NumeroFatura 541800 non-null object 1 CodigoProduto 541800 non-null object 2 NomeProduto 540346 non-null object 3 Quantidade 541800 non-null int64 4 DataVenda 541800 non-null object 5 ValorUnitario 541800 non-null float64 6 IdCliente 406725 non-null float64 7 Pais 541800 non-null object dtypes: float64(2), int64(1), object(5) memory usage: 33.1+ MB
dados.describe()
| Quantidade | ValorUnitario | IdCliente | |
|---|---|---|---|
| count | 541800.000000 | 541800.000000 | 406725.000000 |
| mean | 9.551739 | 4.611581 | 15287.754038 |
| std | 218.103033 | 96.769576 | 1713.475925 |
| min | -80995.000000 | -11062.060000 | 12346.000000 |
| 25% | 1.000000 | 1.250000 | 13954.000000 |
| 50% | 3.000000 | 2.080000 | 15152.000000 |
| 75% | 10.000000 | 4.130000 | 16791.000000 |
| max | 80995.000000 | 38970.000000 | 18287.000000 |
# Alterando tipo de variável
dados['DataVenda'] = pd.to_datetime(dados['DataVenda'])
# Verificando valores nulos
dados.isna().sum()
NumeroFatura 0 CodigoProduto 0 NomeProduto 1454 Quantidade 0 DataVenda 0 ValorUnitario 0 IdCliente 135075 Pais 0 dtype: int64
# Conhecendo o Range da variável 'DataVenda'
print("Data minima: ", dados['DataVenda'].min())
print("Data Máxima: ", dados['DataVenda'].max())
Data minima: 2010-12-01 08:26:00 Data Máxima: 2011-12-09 12:50:00
# Verificando quais países fazem parte da variável 'Pais'
dados.Pais.unique()
array(['Brasil', 'Uruguai', 'Australia', 'Holanda', 'Alemanha', 'Noruega',
'Irlanda', 'Espanha', 'Poland', 'Portugal', 'Italy', 'Belgium',
'Lithuania', 'Japan', 'Iceland', 'Channel Islands', 'Dinamarca',
'Cyprus', 'Sweden', 'Austria', 'Israel', 'Finland', 'Bahrain',
'Greece', 'Hong Kong', 'Cingapura', 'Iraque', 'Equador',
'Saudi Arabia', 'Czech Republic', 'Canada', 'China', 'Inglaterra',
'USA', 'Chile', 'Malta', 'Paraguai'], dtype=object)
# Identificador
dados['AnoMes'] = dados['DataVenda'].map(lambda date: 100 * date.year + date.month)
dados.head(3)
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 |
# Criando variável 'Faturamento'
dados['Faturamento'] = dados['Quantidade'] * dados['ValorUnitario']
dados.head(3)
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.50 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.30 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
# Obtendo faturamento total por mês
df_faturamento = dados.groupby(['AnoMes']).agg({'Faturamento': sum}).reset_index()
df_faturamento
| AnoMes | Faturamento | |
|---|---|---|
| 0 | 201012 | 748957.020 |
| 1 | 201101 | 560000.260 |
| 2 | 201102 | 498062.650 |
| 3 | 201103 | 683267.080 |
| 4 | 201104 | 493207.121 |
| 5 | 201105 | 723333.510 |
| 6 | 201106 | 691123.120 |
| 7 | 201107 | 681300.111 |
| 8 | 201108 | 682680.510 |
| 9 | 201109 | 1019687.622 |
| 10 | 201110 | 1070704.670 |
| 11 | 201111 | 1461756.250 |
| 12 | 201112 | 431245.000 |
# Plot
# Definição dos dados no plot
plot_data = [go.Scatter(x = df_faturamento['AnoMes'],
y = df_faturamento['Faturamento'],)]
# Layout
plot_layout = go.Layout(xaxis = {"type": "category"},
title = 'Faturamento Mensal')
# Plot da figura
fig = go.Figure(data = plot_data, layout = plot_layout)
pyoff.iplot(fig)
Taxa Percentual de crescimento Mensal = Faturamento Mensal / Faturamento Mensal Anterior * 100
# Calculando a diferença percentual em relação à observação anterior e criando nova variável.
df_faturamento['CrescimentoMensal'] = df_faturamento['Faturamento'].pct_change()
df_faturamento['CrescimentoMensal'].replace(np.nan, 0, inplace=True)
df_faturamento.head()
| AnoMes | Faturamento | CrescimentoMensal | |
|---|---|---|---|
| 0 | 201012 | 748957.020 | 0.000000 |
| 1 | 201101 | 560000.260 | -0.252293 |
| 2 | 201102 | 498062.650 | -0.110603 |
| 3 | 201103 | 683267.080 | 0.371850 |
| 4 | 201104 | 493207.121 | -0.278163 |
# Plot
# Definição dos dados no plot (filtramos o mês 12 de 2011 pois não temos dados suficientes)
plot_data = [go.Scatter(x = df_faturamento.query('AnoMes < 201112')['AnoMes'],
y = df_faturamento.query('AnoMes < 201112')['CrescimentoMensal'], )]
# Layout
plot_layout= go.Layout(xaxis = {"type": "category"},
title = 'Taxa Percentual de Crescimento Mensal')
# Plot da figura
fig = go.Figure(data = plot_data, layout=plot_layout)
pyoff.iplot(fig)
clientes ativos são aqueles que fizeram uma compra em cada mês
dados.head(3)
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.50 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.30 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
sss = dados.groupby(['AnoMes'])['IdCliente'].unique().reset_index()
sss
| AnoMes | IdCliente | |
|---|---|---|
| 0 | 201012 | [17850.0, 13047.0, 12583.0, 13748.0, 15100.0, ... |
| 1 | 201101 | [13313.0, nan, 18097.0, 16656.0, 16875.0, 1309... |
| 2 | 201102 | [15240.0, 14911.0, 14496.0, 17147.0, 17675.0, ... |
| 3 | 201103 | [14620.0, 14740.0, 13880.0, 16462.0, 17068.0, ... |
| 4 | 201104 | [18161.0, 14886.0, 17613.0, 12523.0, 13694.0, ... |
| 5 | 201105 | [15606.0, 14800.0, 16931.0, 15708.0, 14304.0, ... |
| 6 | 201106 | [15643.0, 14842.0, 15124.0, 14646.0, 12423.0, ... |
| 7 | 201107 | [16317.0, 13492.0, 14911.0, 17865.0, 17667.0, ... |
| 8 | 201108 | [17941.0, 14947.0, 12921.0, 14060.0, 14239.0, ... |
| 9 | 201109 | [13509.0, nan, 13305.0, 16187.0, 17306.0, 1247... |
| 10 | 201110 | [16353.0, 16591.0, 16923.0, 15038.0, 17811.0, ... |
| 11 | 201111 | [17733.0, 17419.0, 13461.0, 13697.0, 14911.0, ... |
| 12 | 201112 | [13853.0, 15197.0, 13644.0, 13310.0, 13468.0, ... |
sss.IdCliente
0 [17850.0, 13047.0, 12583.0, 13748.0, 15100.0, ... 1 [13313.0, nan, 18097.0, 16656.0, 16875.0, 1309... 2 [15240.0, 14911.0, 14496.0, 17147.0, 17675.0, ... 3 [14620.0, 14740.0, 13880.0, 16462.0, 17068.0, ... 4 [18161.0, 14886.0, 17613.0, 12523.0, 13694.0, ... 5 [15606.0, 14800.0, 16931.0, 15708.0, 14304.0, ... 6 [15643.0, 14842.0, 15124.0, 14646.0, 12423.0, ... 7 [16317.0, 13492.0, 14911.0, 17865.0, 17667.0, ... 8 [17941.0, 14947.0, 12921.0, 14060.0, 14239.0, ... 9 [13509.0, nan, 13305.0, 16187.0, 17306.0, 1247... 10 [16353.0, 16591.0, 16923.0, 15038.0, 17811.0, ... 11 [17733.0, 17419.0, 13461.0, 13697.0, 14911.0, ... 12 [13853.0, 15197.0, 13644.0, 13310.0, 13468.0, ... Name: IdCliente, dtype: object
lista = []
for i in sss.IdCliente:
a = len(i)
lista.append(a)
df_faturamento['Clientes_At'] = lista
df_faturamento.columns = ['AnoMes', 'Faturamento', 'CrescimentoMensal', 'Clientes_Atv_World']
df_faturamento.head(3)
| AnoMes | Faturamento | CrescimentoMensal | Clientes_Atv_World | |
|---|---|---|---|---|
| 0 | 201012 | 748957.02 | 0.000000 | 949 |
| 1 | 201101 | 560000.26 | -0.252293 | 784 |
| 2 | 201102 | 498062.65 | -0.110603 | 799 |
dados_brasil = dados.query("Pais =='Brasil'").reset_index(drop = True)
dados_brasil.head()
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.50 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.30 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
| 3 | 536365 | 84406B | CREAM CUPID HEARTS COAT HANGER | 8 | 2010-12-01 08:26:00 | 2.75 | 17850.0 | Brasil | 201012 | 22.00 |
| 4 | 536365 | 84029G | KNITTED UNION FLAG HOT WATER BOTTLE | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
# Clientes Ativos somente no brasil por mês
df_ativos_mes = dados_brasil.groupby(['AnoMes'])['IdCliente'].nunique().reset_index()
df_ativos_mes.head(3)
| AnoMes | IdCliente | |
|---|---|---|
| 0 | 201012 | 871 |
| 1 | 201101 | 684 |
| 2 | 201102 | 714 |
df_faturamento['Clientes_Atv_Brasil'] = df_ativos_mes.IdCliente
df_faturamento.head(3)
| AnoMes | Faturamento | CrescimentoMensal | Clientes_Atv_World | Clientes_Atv_Brasil | |
|---|---|---|---|---|---|
| 0 | 201012 | 748957.02 | 0.000000 | 949 | 871 |
| 1 | 201101 | 560000.26 | -0.252293 | 784 | 684 |
| 2 | 201102 | 498062.65 | -0.110603 | 799 | 714 |
# Plot
# Definição dos dados no plot
plot_data = [go.Bar(x=df_ativos_mes['AnoMes'],
y=df_ativos_mes['IdCliente'],)]
# Layout
plot_layout = go.Layout(xaxis = {"type":"category"},
title = 'Clientes Ativos por mês em um País (Brasil)')
# Plot figura
fig = go.Figure(data = plot_data, layout=plot_layout)
pyoff.iplot(fig)
Total de itens comprados por mês
# Agrupa os dados para calcular o total de itens comprados por mês no Brasil
df_itens_mes = dados_brasil.groupby(['AnoMes'])['Quantidade'].sum().reset_index()
df_itens_mes.head()
| AnoMes | Quantidade | |
|---|---|---|
| 0 | 201012 | 298101 |
| 1 | 201101 | 237381 |
| 2 | 201102 | 225641 |
| 3 | 201103 | 279843 |
| 4 | 201104 | 257666 |
# Plot
# Plot dados
plot_dados = [go.Bar(x=df_itens_mes['AnoMes'],
y=df_itens_mes['Quantidade'],)]
# Plot_layout
plot_layout = go.Layout(xaxis={"type":"category"},
title = 'Quant. Itens comprados por Mês no Brasil')
# Figura
fig = go.Figure(data=plot_dados, layout=plot_layout)
pyoff.iplot(fig)
Faturamento médio por mês em um país.
# Calcula o faturamento médio
df_faturamento_medio = dados_brasil.groupby(['AnoMes'])['Faturamento'].mean().reset_index()
df_faturamento_medio.head()
| AnoMes | Faturamento | |
|---|---|---|
| 0 | 201012 | 16.865860 |
| 1 | 201101 | 13.614680 |
| 2 | 201102 | 16.093027 |
| 3 | 201103 | 16.716166 |
| 4 | 201104 | 15.773380 |
# Plot
# plot dados
plot_data = [go.Bar(x=df_faturamento_medio['AnoMes'],
y =df_faturamento_medio['Faturamento'],)]
# Plot_LAyout
plot_layout = go.Layout(xaxis={"type":"category"},
title="Faturamento médio Mensal (Brasil)")
# PLot_Figure
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
# Calcula o faturamento total BRASIL
df_faturamento_soma = dados_brasil.groupby(['AnoMes'])['Faturamento'].sum().reset_index()
# Plot
# plot dados
plot_data = [go.Bar(x=df_faturamento_soma['AnoMes'],
y =df_faturamento_soma['Faturamento'],)]
# Plot_LAyout
plot_layout = go.Layout(xaxis={"type":"category"},
title="Faturamento Total Mensal (Brasil)")
# PLot_Figure
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Para calcular esse indicador precisaremos de um pouco mais de criatividade. O que é um cliente novo ou antigo?
Vamos considerar clientes novo aquele com baixo volume de compras e clientes antigos aquele com alto volume de compras.
# Vamos encontrar a adta de menor volume de compras de cada cliente
df_data_minima = dados.groupby(['IdCliente'])['DataVenda'].min().reset_index()
df_data_minima
| IdCliente | DataVenda | |
|---|---|---|
| 0 | 12346.0 | 2011-01-18 10:01:00 |
| 1 | 12347.0 | 2010-12-07 14:57:00 |
| 2 | 12348.0 | 2010-12-16 19:09:00 |
| 3 | 12349.0 | 2011-11-21 09:51:00 |
| 4 | 12350.0 | 2011-02-02 16:01:00 |
| ... | ... | ... |
| 4367 | 18280.0 | 2011-03-07 09:52:00 |
| 4368 | 18281.0 | 2011-06-12 10:53:00 |
| 4369 | 18282.0 | 2011-08-05 13:35:00 |
| 4370 | 18283.0 | 2011-01-06 14:14:00 |
| 4371 | 18287.0 | 2011-05-22 10:39:00 |
4372 rows × 2 columns
# Ajustamos os nomes das colunas
df_data_minima.columns = ['IdCliente','Data_ingresso']
df_data_minima.head(2)
| IdCliente | Data_ingresso | |
|---|---|---|
| 0 | 12346.0 | 2011-01-18 10:01:00 |
| 1 | 12347.0 | 2010-12-07 14:57:00 |
# Vamos extrair o mês em que foi registrada a primeira compra do cliente
df_data_minima['Mes_primeira_Compra_Cliente'] = df_data_minima['Data_ingresso'].map(lambda date: 100 * date.year + date.month)
df_compra_minima.head()
| IdCliente | Data_ingresso | Mes_primeira_Compra_Cliente | |
|---|---|---|---|
| 0 | 12346.0 | 2011-01-18 10:01:00 | 201101 |
| 1 | 12347.0 | 2010-12-07 14:57:00 | 201012 |
| 2 | 12348.0 | 2010-12-16 19:09:00 | 201012 |
| 3 | 12349.0 | 2011-11-21 09:51:00 | 201111 |
| 4 | 12350.0 | 2011-02-02 16:01:00 | 201102 |
dados.head()
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.50 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.30 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
| 3 | 536365 | 84406B | CREAM CUPID HEARTS COAT HANGER | 8 | 2010-12-01 08:26:00 | 2.75 | 17850.0 | Brasil | 201012 | 22.00 |
| 4 | 536365 | 84029G | KNITTED UNION FLAG HOT WATER BOTTLE | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 |
# Vamos fazer um merge entre o data original e o dataset de data de ingresso
df_3 = pd.merge(dados, df_data_minima, on='IdCliente')
df_3.head()
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | Data_ingresso | Mes_primeira_Compra_Cliente | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.50 | 2010-12-01 08:26:00 | 201012 |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.30 | 2010-12-01 08:26:00 | 201012 |
| 2 | 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 | 2010-12-01 08:26:00 | 201012 |
| 3 | 536365 | 84406B | CREAM CUPID HEARTS COAT HANGER | 8 | 2010-12-01 08:26:00 | 2.75 | 17850.0 | Brasil | 201012 | 22.00 | 2010-12-01 08:26:00 | 201012 |
| 4 | 536365 | 84029G | KNITTED UNION FLAG HOT WATER BOTTLE | 6 | 2010-12-01 08:26:00 | 3.39 | 17850.0 | Brasil | 201012 | 20.34 | 2010-12-01 08:26:00 | 201012 |
# Vamos criar uma nova coluna de tipo de usuário e preencher com Novo
df_3['TipoUsuario'] = 'Novo'
df_3.head(2)
| NumeroFatura | CodigoProduto | NomeProduto | Quantidade | DataVenda | ValorUnitario | IdCliente | Pais | AnoMes | Faturamento | Data_ingresso | Mes_primeira_Compra_Cliente | TipoUsuario | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 536365 | 21730 | GLASS STAR FROSTED T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 4.25 | 17850.0 | Brasil | 201012 | 25.5 | 2010-12-01 08:26:00 | 201012 | Novo |
| 1 | 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850.0 | Brasil | 201012 | 15.3 | 2010-12-01 08:26:00 | 201012 | Novo |
df_3['TipoUsuario'].value_counts()
Novo 406725 Name: TipoUsuario, dtype: int64
# Um cliente antigo é aquele cuja data de compras no mês é maior que a data de ingresso
# Se for verdadeiro, mudamos a coluna TipoUsuario para "Antigo" e se não, mantemos como "Novo"
df_3['TipoUsuario'] = np.where(df_3['Mes_primeira_Compra_Cliente'] < df_3['AnoMes'], 'Antigo', 'Novo')
df_3['TipoUsuario'].value_counts()
Antigo 287549 Novo 119176 Name: TipoUsuario, dtype: int64
# Agora calculamos o faturamento por tipo de usuário por mês
df_diff = df_3.groupby(['AnoMes','TipoUsuario'])['Faturamento'].sum().reset_index()
# Removendo meses que nõo possuímos dados suficientes.
df_diff = df_diff.query("AnoMes != 201012 and AnoMes != 201112")
df_diff
| AnoMes | TipoUsuario | Faturamento | |
|---|---|---|---|
| 1 | 201101 | Antigo | 271616.520 |
| 2 | 201101 | Novo | 203457.860 |
| 3 | 201102 | Antigo | 287024.770 |
| 4 | 201102 | Novo | 149521.380 |
| 5 | 201103 | Antigo | 390034.530 |
| 6 | 201103 | Novo | 189930.080 |
| 7 | 201104 | Antigo | 306283.600 |
| 8 | 201104 | Novo | 119764.251 |
| 9 | 201105 | Antigo | 532392.340 |
| 10 | 201105 | Novo | 115858.740 |
| 11 | 201106 | Antigo | 515486.650 |
| 12 | 201106 | Novo | 92526.510 |
| 13 | 201107 | Antigo | 508355.610 |
| 14 | 201107 | Novo | 65882.871 |
| 15 | 201108 | Antigo | 538709.770 |
| 16 | 201108 | Novo | 77658.230 |
| 17 | 201109 | Antigo | 778161.781 |
| 18 | 201109 | Novo | 153278.591 |
| 19 | 201110 | Antigo | 819672.900 |
| 20 | 201110 | Novo | 154930.690 |
| 21 | 201111 | Antigo | 998176.360 |
| 22 | 201111 | Novo | 134231.380 |
dados.nunique()
NumeroFatura 25892 CodigoProduto 4070 NomeProduto 4223 Quantidade 722 DataVenda 23253 ValorUnitario 1630 IdCliente 4372 Pais 37 AnoMes 13 Faturamento 6204 dtype: int64
# Plot
#Definiçào dos dados no plot
plot_data = [go.Scatter(x=df_diff.query("TipoUsuario == 'Antigo'")['AnoMes'],
y=df_diff.query("TipoUsuario == 'Antigo'")['Faturamento'],
name='Cliente Antigo'),
go.Scatter(x=df_diff.query("TipoUsuario == 'Novo'")['AnoMes'],
y=df_diff.query("TipoUsuario == 'Novo'")['Faturamento'],
name='Cliente Antigo')]
# Dafinindo plot LAyout
plot_layout = go.Layout(xaxis = {"type":"category"},
title = 'Diferença de Faturamento ao Longo do Tempo entre Clientes (Novos vs. Antigos)')
# Plot Figura
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Como definimos clientes novos e antigos no indicador 6, agora podemos usar os dados e calcular a proporção de novos clientes ao longo do tempo.
# calcula a taxa de novos clientes
df_tx_new_client = df_3.query("TipoUsuario == 'Novo'").groupby(['AnoMes'])['IdCliente'].nunique() / df_3.query("TipoUsuario == 'Antigo'").groupby(['AnoMes'])['IdCliente'].nunique()
df_tx_new_client.head()
AnoMes 201012 NaN 201101 1.162983 201102 0.909091 201103 0.758621 201104 0.498333 Name: IdCliente, dtype: float64
df_tx_new_client = df_tx_new_client.reset_index()
df_tx_new_client = df_tx_new_client.dropna()
df_tx_new_client.columns = ['AnoMes','Tx_new_clients']
df_tx_new_client.head()
| AnoMes | Tx_new_clients | |
|---|---|---|
| 1 | 201101 | 1.162983 |
| 2 | 201102 | 0.909091 |
| 3 | 201103 | 0.758621 |
| 4 | 201104 | 0.498333 |
| 5 | 201105 | 0.348750 |
# Plot
plot_data = [go.Bar(x=df_tx_new_client.query('AnoMes > 201101 and AnoMes < 201112')['AnoMes'],
y=df_tx_new_client.query('AnoMes > 201101 and AnoMes < 201112')['Tx_new_clients'],)]
plot_layout = go.Layout(xaxis={"type":"category"},
title='Taxa de Novos Clientes')
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Taxa mensal de retenção de clientes = Clientes do mês anterior / Total de Clientes Ativos
# Agrupamos os dados por cliente e mês e somamos o faturamento
df_tx_M_clients = df_3.groupby(['IdCliente','AnoMes'])['Faturamento'].sum().reset_index()
df_tx_M_clients.head()
| IdCliente | AnoMes | Faturamento | |
|---|---|---|---|
| 0 | 12346.0 | 201101 | 0.00 |
| 1 | 12347.0 | 201012 | 711.79 |
| 2 | 12347.0 | 201101 | 475.39 |
| 3 | 12347.0 | 201104 | 636.25 |
| 4 | 12347.0 | 201106 | 382.52 |
# Agora definimos a retenção com uma tabela cruzada
df_ret = pd.crosstab(df_tx_M_clients['IdCliente'], df_tx_M_clients['AnoMes']).reset_index()
df_ret
| AnoMes | IdCliente | 201012 | 201101 | 201102 | 201103 | 201104 | 201105 | 201106 | 201107 | 201108 | 201109 | 201110 | 201111 | 201112 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 12346.0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 12347.0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
| 2 | 12348.0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
| 3 | 12349.0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
| 4 | 12350.0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4367 | 18280.0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4368 | 18281.0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4369 | 18282.0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| 4370 | 18283.0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 |
| 4371 | 18287.0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
4372 rows × 14 columns
# Extraimos os meses
meses = df_ret.columns[2:]
meses
Index([201101, 201102, 201103, 201104, 201105, 201106, 201107, 201108, 201109,
201110, 201111, 201112],
dtype='object', name='AnoMes')
# loop abaixo vai calcular a retenção ao longo dos meses
# Lista para gravar o resultado
lista_ret = []
# loopp
for i in range(len(meses)-1):
dados_retencao = {}
mes_corrente = meses[i+1]
mes_anterior = meses[i]
dados_retencao['AnoMes'] = int(mes_corrente)
dados_retencao['TotalUser'] = df_ret[mes_corrente].sum()
dados_retencao['TotalRetido'] = df_ret[(df_ret[mes_corrente] > 0) & (df_ret[mes_anterior] > 0)][mes_corrente].sum()
lista_ret.append(dados_retencao)
lista_ret
[{'AnoMes': 201102, 'TotalUser': 798, 'TotalRetido': 299},
{'AnoMes': 201103, 'TotalUser': 1020, 'TotalRetido': 345},
{'AnoMes': 201104, 'TotalUser': 899, 'TotalRetido': 346},
{'AnoMes': 201105, 'TotalUser': 1079, 'TotalRetido': 399},
{'AnoMes': 201106, 'TotalUser': 1051, 'TotalRetido': 464},
{'AnoMes': 201107, 'TotalUser': 993, 'TotalRetido': 415},
{'AnoMes': 201108, 'TotalUser': 980, 'TotalRetido': 433},
{'AnoMes': 201109, 'TotalUser': 1302, 'TotalRetido': 465},
{'AnoMes': 201110, 'TotalUser': 1425, 'TotalRetido': 552},
{'AnoMes': 201111, 'TotalUser': 1711, 'TotalRetido': 690},
{'AnoMes': 201112, 'TotalUser': 683, 'TotalRetido': 440}]
df_ret_final = pd.DataFrame(lista_ret)
df_ret_final
| AnoMes | TotalUser | TotalRetido | |
|---|---|---|---|
| 0 | 201102 | 798 | 299 |
| 1 | 201103 | 1020 | 345 |
| 2 | 201104 | 899 | 346 |
| 3 | 201105 | 1079 | 399 |
| 4 | 201106 | 1051 | 464 |
| 5 | 201107 | 993 | 415 |
| 6 | 201108 | 980 | 433 |
| 7 | 201109 | 1302 | 465 |
| 8 | 201110 | 1425 | 552 |
| 9 | 201111 | 1711 | 690 |
| 10 | 201112 | 683 | 440 |
# Calculamos o indicador
df_ret_final['TaxaRetencao'] = df_ret_final['TotalRetido'] / df_ret_final['TotalUser'] * 100
df_ret_final
| AnoMes | TotalUser | TotalRetido | TaxaRetencao | |
|---|---|---|---|---|
| 0 | 201102 | 798 | 299 | 37.468672 |
| 1 | 201103 | 1020 | 345 | 33.823529 |
| 2 | 201104 | 899 | 346 | 38.487208 |
| 3 | 201105 | 1079 | 399 | 36.978684 |
| 4 | 201106 | 1051 | 464 | 44.148430 |
| 5 | 201107 | 993 | 415 | 41.792548 |
| 6 | 201108 | 980 | 433 | 44.183673 |
| 7 | 201109 | 1302 | 465 | 35.714286 |
| 8 | 201110 | 1425 | 552 | 38.736842 |
| 9 | 201111 | 1711 | 690 | 40.327294 |
| 10 | 201112 | 683 | 440 | 64.421669 |
# Plot
# Data
plot_data = [go.Scatter(x=df_ret_final.query('AnoMes < 201112')['AnoMes'],
y=df_ret_final.query('AnoMes < 201112')['TaxaRetencao'],
name='Taxa')]
# Layout
plot_layout = go.Layout(xaxis = {"type":"category"},
title = 'Taxa Mensal de Retenção de Clientes')
# Figure
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)